//
// Created by konglinglong on 2020/9/8.
//

#include <stdio.h>
#include <iostream>
#include "../lib/doctest.h"
#include "../../include/utils/fixRingBuffer.h"

using namespace std;

TEST_SUITE ("FIX_RB_TS")
{
    TEST_CASE ("FIX_RB_TC")
    {
        int32_t rc;
        uint32_t ringBuffType;
        S_FixRingBuffer* pRingBuffer;

        SUBCASE("FIX_RB_SC_BASE")
        {
            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);
                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_BASE2")
        {
            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1025, 1024, ringBuffType);
                REQUIRE(!pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_DUMP")
        {
            char dumpBuffer[2048];

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                FixRB_Dump(pRingBuffer, dumpBuffer, sizeof(dumpBuffer));
                printf("%s\n", dumpBuffer);

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_READ_WRITE")
        {
            char* pBuffer;
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                pBuffer = (char*)FixRB_WriteRequest(pRingBuffer, 1024);
                REQUIRE(pBuffer);
                rc = FixRB_WriteCommit(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                pBuffer = (char*)FixRB_ReadRequest(pRingBuffer, &buffSize);
                REQUIRE(pBuffer);
                REQUIRE(1024 == buffSize);
                rc = FixRB_ReadConsume(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_READ_WRITE_SHM")
        {
            char* pBuffer;
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create("FixRB_Shm", 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                pBuffer = (char*)FixRB_WriteRequest(pRingBuffer, 1024);
                REQUIRE(pBuffer);
                rc = FixRB_WriteCommit(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                pBuffer = (char*)FixRB_ReadRequest(pRingBuffer, &buffSize);
                REQUIRE(pBuffer);
                REQUIRE(1024 == buffSize);
                rc = FixRB_ReadConsume(pRingBuffer, pBuffer);
                REQUIRE(CSP_RC_OK == rc);

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_READ_WRITE2")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t ringBuffType;
            char* pBuffer;
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                loopCnt = rand() % 10000;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    pBuffer = (char*)FixRB_WriteRequest(pRingBuffer, 1024);
                    REQUIRE(pBuffer);
                    rc = FixRB_WriteCommit(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);

                    pBuffer = (char*)FixRB_ReadRequest(pRingBuffer, &buffSize);
                    REQUIRE(pBuffer);
                    REQUIRE(1024 == buffSize);
                    rc = FixRB_ReadConsume(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);
                }

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_READ_WRITE3")
        {
            uint32_t loop;
            uint32_t loopCnt;
            char* pBuffer;
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                loopCnt = rand() % 1024;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    pBuffer = (char*)FixRB_WriteRequest(pRingBuffer, 1024);
                    REQUIRE(pBuffer);
                    rc = FixRB_WriteCommit(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(loopCnt == FixRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    pBuffer = (char*)FixRB_ReadRequest(pRingBuffer, &buffSize);
                    REQUIRE(pBuffer);
                    REQUIRE(1024 == buffSize);
                    rc = FixRB_ReadConsume(pRingBuffer, pBuffer);
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(0 == FixRB_Count(pRingBuffer));

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_PUT_GET")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t buffer[1024 / sizeof(uint32_t)];
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                loopCnt = rand() % 1024;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffer[0] = loop;
                    rc = FixRB_Put(pRingBuffer, buffer, sizeof(buffer));
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(loopCnt == FixRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffSize = sizeof(buffer);
                    rc = FixRB_Get(pRingBuffer, buffer, &buffSize);
                    REQUIRE(CSP_RC_OK == rc);
                    REQUIRE(sizeof(buffer) == buffSize);
                    REQUIRE(loop == buffer[0]);
                }
                REQUIRE(0 == FixRB_Count(pRingBuffer));

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_PUT_GET1")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t buffer[1024 / sizeof(uint32_t)];
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create(NULL, 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                loopCnt = 1024;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffer[0] = loop;
                    rc = FixRB_Put(pRingBuffer, buffer, sizeof(buffer));
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(loopCnt == FixRB_Count(pRingBuffer));
                rc = FixRB_Put(pRingBuffer, buffer, sizeof(buffer));
                REQUIRE(CSP_RC_ER == rc);

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffSize = sizeof(buffer);
                    rc = FixRB_Get(pRingBuffer, buffer, &buffSize);
                    REQUIRE(CSP_RC_OK == rc);
                    REQUIRE(sizeof(buffer) == buffSize);
                    REQUIRE(loop == buffer[0]);
                }
                REQUIRE(0 == FixRB_Count(pRingBuffer));
                rc = FixRB_Get(pRingBuffer, buffer, &buffSize);
                REQUIRE(CSP_RC_ER == rc);

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        SUBCASE("FIX_RB_SC_PUT_GET_SHM")
        {
            uint32_t loop;
            uint32_t loopCnt;
            uint32_t buffer[1024 / sizeof(uint32_t)];
            uint32_t buffSize;

            ringBuffType = FIX_RB_TYPE_NONE;
            while (ringBuffType <= FIX_RB_TYPE_MPMC)
            {
                pRingBuffer = FixRB_Create("uint_test_frb_shm", 1024, 1024, ringBuffType);
                REQUIRE(pRingBuffer);

                loopCnt = rand() % 1024;

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffer[0] = loop;
                    rc = FixRB_Put(pRingBuffer, buffer, sizeof(buffer));
                    REQUIRE(CSP_RC_OK == rc);
                }
                REQUIRE(loopCnt == FixRB_Count(pRingBuffer));

                for (loop = 0; loop < loopCnt; loop++)
                {
                    buffSize = sizeof(buffer);
                    rc = FixRB_Get(pRingBuffer, buffer, &buffSize);
                    REQUIRE(CSP_RC_OK == rc);
                    REQUIRE(sizeof(buffer) == buffSize);
                    REQUIRE(loop == buffer[0]);
                }
                REQUIRE(0 == FixRB_Count(pRingBuffer));

                FixRB_Destroy(pRingBuffer);
                ringBuffType++;
            }
        }

        REQUIRE(OS_MemGetAllocCount() == OS_MemGetFreeCount());
    }
}
